#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include "esp_wifi.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_event.h"
#include "esp_netif.h"
#include "esp_mac.h"

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"

#include "lwip/sockets.h"
#include "lwip/dns.h"
#include "lwip/netdb.h"

#include "mbedtls/md5.h"
#include "esp_log.h"
#include "mqtt_client.h"
#include "my_wss.h"
#include "cJSON.h"
#include "led.h"
#include "get_time.h"
#include "my_uart.h"
#include "BedSpread.h"
#include "ota.h"
#include "esp_app_desc.h"
#include "esp_ota_ops.h"

#define CONFIG_XLINK_DEVICE_ID 12345

static uint8_t g_esp_mac[6] = {0};
char mac_str[13] = {0}; // mac地址
int Subscribe_End = 0;  // 订阅完成标志位
int First_Read = 1;
myCJson cjson_data;
char g_publish_topic[100] = "";
char subscribe_topic[100] = "";
char Json_Append[20] = {0};

esp_mqtt_client_handle_t my_client;

static const char *TAG = "MQTTWSS_EXAMPLE";

#if CONFIG_BROKER_CERTIFICATE_OVERRIDDEN == 1
static const uint8_t mqtt_eclipseprojects_io_pem_start[] = "-----BEGIN CERTIFICATE-----\n" CONFIG_BROKER_CERTIFICATE_OVERRIDE "\n-----END CERTIFICATE-----";
#else
extern const uint8_t mqtt_eclipseprojects_io_pem_start[] asm("_binary_mqtt_eclipseprojects_io_pem_start");
#endif
extern const uint8_t mqtt_eclipseprojects_io_pem_end[] asm("_binary_mqtt_eclipseprojects_io_pem_end");

static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data);
static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event);

void mqtt_app_start(void)
{
    // ESP_LOGI(TAG, "[APP] Startup..");
    // ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size());
    // ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version());

    esp_log_level_set("*", ESP_LOG_INFO);
    esp_log_level_set("MQTT_CLIENT", ESP_LOG_VERBOSE);
    esp_log_level_set("MQTT_EXAMPLE", ESP_LOG_VERBOSE);
    esp_log_level_set("TRANSPORT_BASE", ESP_LOG_VERBOSE);
    esp_log_level_set("TRANSPORT", ESP_LOG_VERBOSE);
    esp_log_level_set("OUTBOX", ESP_LOG_VERBOSE);

    char mqtt_clientid[32] = {0};
    uint32_t device_id = CONFIG_XLINK_DEVICE_ID;
    sprintf(mqtt_clientid, "Alive-RDBed-%ld", device_id);
    printf("%s\n", mqtt_clientid);
    esp_mqtt_client_config_t mqtt_cfg = {
        .session.disable_clean_session = true, // 设置为 true，以清除之前的会话数据
        .broker.address.uri = "wss://mesh.szalive.com:8084/mqtt",
        .credentials = {
            .username = "alive",                      // 用户名
            .client_id = mqtt_clientid,               // 客户端ID
            .authentication.password = "alivegogogo", // 密码
        },
        .buffer.out_size = 2048,
        .buffer.size = 2048,
        .broker.verification.certificate = (const char *)mqtt_eclipseprojects_io_pem_start, /*证书数据*/
    };

    ESP_LOGI(TAG, "[APP] Free memory: %lu bytes", (unsigned long)esp_get_free_heap_size()); // 获取可用堆的大小。
    // 初始化mqtt，返回值为客户端句柄
    esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
    // 注册 MQTT事件
    esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
    // 启动MQTT
    esp_mqtt_client_start(client);
}

/*传给 esp_mqtt_client_register_event 的参数可作为 handler_args 访问*/
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
    ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%" PRId32 "", base, event_id);
    mqtt_event_handler_cb(event_data);
}
static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event)
{
    nvs_handle_t my_handle;
    esp_err_t err;
    esp_mqtt_client_handle_t client = event->client;
    my_client = client;
    int msg_id;
    switch (event->event_id)
    {
    case MQTT_EVENT_CONNECTED:
        bed_tx = 4;
        while (bed_tx != 0)
        {
            vTaskDelay(10 / portTICK_PERIOD_MS); // 为了避免持续占用CPU，适当地加入延时
        }
        ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
        packet_publish_topic(g_publish_topic);
        packet_subscribe_topic(subscribe_topic);
        msg_id = esp_mqtt_client_subscribe(client, subscribe_topic, 0);
        Subscribe_End = 1;
        ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
        // ESP_LOGI(TAG, "sent unsubscribe successful, msg_id=%d", msg_id);
        break;
    case MQTT_EVENT_DISCONNECTED:
        bed_tx = 7;
        while (bed_tx != 0)
        {
            vTaskDelay(10 / portTICK_PERIOD_MS); // 为了避免持续占用CPU，适当地加入延时
        }
        ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
        memset(subscribe_topic, 0, 60);
        break;
    case MQTT_EVENT_SUBSCRIBED:
        // Subscribe_End++;
        ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
        // 发布首次连接消息
        if (Subscribe_End == 1)
        {
            bed_tx = 4;
            while (bed_tx != 0)
            {
                vTaskDelay(10 / portTICK_PERIOD_MS); // 为了避免持续占用CPU，适当地加入延时
            }
            Publish_First_Connet(client);
            err = nvs_open("Wifi_Storage", NVS_READWRITE, &my_handle);
            err = nvs_get_i64(my_handle, "WifiTest", &WifiTest);
            if (err != ESP_OK)
            {
                printf("Error (%s) erasing NVS!\n", esp_err_to_name(err));
                WifiTest = 0;
            }
            printf("WifiTest = %d\n", WifiTest);
            if (WifiTest == 1)
            {
                WifiTest = 0;
                Publish_WifiTest_Result(my_client, g_publish_topic, true);
            }
            else if (WifiTest == 2)
            {
                WifiTest = 0;
                Publish_WifiTest_Result(my_client, g_publish_topic, false);
            }
            err = nvs_set_i64(my_handle, "WifiTest", WifiTest);
            nvs_close(my_handle);
            // 读取一次床当前状态
            while (bed_tx != 0)
            {
                vTaskDelay(5 / portTICK_PERIOD_MS);
            }
            bed_tx = 2;
            while (bed_tx != 0)
            {
                vTaskDelay(5 / portTICK_PERIOD_MS);
            }
            Subscribe_End = 0;
        }
        break;
    case MQTT_EVENT_UNSUBSCRIBED:
        ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_PUBLISHED:
        ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_DATA:
        printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
        printf("nowDATA=%.*s\r\n", event->data_len, event->data);

        ESP_LOGI(TAG, "MQTT_EVENT_DATA");
        unsigned char *json_buffer = malloc(event->data_len);
        if (json_buffer != NULL)
        {
            ESP_LOGI(TAG, "json_buffer != NULL");
            ESP_LOGI(TAG, "data_len = %d", event->data_len);
            // 将json数据存入json_buffer
            memcpy(json_buffer, event->data, event->data_len);
            const char *char_buffer = (const char *)json_buffer;
            // 解析json数据
            cJSON *root = cJSON_Parse(char_buffer);
            // 获取要比对的数据，存入结构体 cjson_data
            // 如果命令是上报首次连接
            int ret = get_first_jsondata(root, &cjson_data);
            if (ret)
            {
                // static BaseType_t xreturn;
                ret = 0;
                Get_system_time(&system_timestamp, &cjson_data);
                print_system_time();
                // Bed_ReadState(client, g_publish_topic);
                Bed_SyncPolicy_TaskKey();
            }
            ret = Parse_JsonData(root, &cjson_data);
            if (ret)
            {
                // printf("cjson_data.right_VibInt = %s\n", cjson_data.right_VibInt);
                Run_JsonData(client, g_publish_topic, &cjson_data);
                ret = 0;
            }
        }
        free(json_buffer); // 释放申请的空间

        break;
    case MQTT_EVENT_ERROR:
        ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
        break;
    default:
        ESP_LOGI(TAG, "Other event id:%" PRIu32 "", (uint32_t)event->event_id);
        break;
    }
    return ESP_OK;
}

void Run_JsonData(esp_mqtt_client_handle_t *client, char *topic, myCJson *data)
{
    // if (strcmp(cjson_data.deviceType, "SmartDevice") == 0 &&
    //     strcmp(cjson_data.deviceMAC, mac_str) == 0 &&
    //     strcmp(cjson_data.operate, "sync") == 0 &&
    //     strcmp(cjson_data.type, "esp32ota") == 0) // 判断是OTA升级命令
    // {
    //     ESP_LOGI(TAG, "It is OTA cmd!!!");
    //     printf("%s\n", cjson_data.sub_downloadLink);
    //     ota_mcu_start(cjson_data.sub_downloadLink);
    // }
    nvs_handle_t my_handle;
    esp_err_t err;
    if (strcmp(cjson_data.operate, "sync") == 0 &&
        strcmp(cjson_data.type, "esp32ota") == 0) // 判断是OTA升级命令
    {
        ESP_LOGI(TAG, "It is OTA cmd!!!");
        printf("%s\n", cjson_data.sub_downloadLink);
        ota_mcu_start(cjson_data.sub_downloadLink);
    }

    if (strcmp(cjson_data.deviceType, "SmartDevice") == 0 &&
        strcmp(cjson_data.deviceMAC, mac_str) == 0 &&
        strcmp(cjson_data.operate, "control") == 0 &&
        strcmp(cjson_data.type, "controller") == 0) // 判断是控制床垫报文
    {
        ESP_LOGI(TAG, "It is control cmd!!!");

        if (Bed_Control_State[0] == 1)
        {
            Bed_Write.bed_key = safe_atoi(cjson_data.bed_key);
            // 记得存储床左右的开关状态
            err = nvs_open(Bed_Storage, NVS_READWRITE, &my_handle);
            err = nvs_set_blob(my_handle, "Bed_Write", &Bed_Write, sizeof(BedSpread));
            if (err != ESP_OK)
            {
                printf("存储开关状态失败\n");
            }
            err = nvs_commit(my_handle);
            nvs_close(my_handle);
        }
        if (Bed_Control_State[1] == 1)
        {
            Bed_Write.left_mode = safe_atoi(cjson_data.left_mode);
        }
        if (Bed_Control_State[2] == 1)
        {
            Bed_Write.right_mode = safe_atoi(cjson_data.right_mode);
        }
        if (Bed_Control_State[3] == 1)
        {
            Bed_Write.left_settemp = safe_atoi(cjson_data.left_temp);
        }
        if (Bed_Control_State[4] == 1)
        {
            Bed_Write.right_settemp = safe_atoi(cjson_data.right_temp);
        }
        // 有左区定时任务
        if (Bed_Control_State[5] == 1)
        {
            Bed_Write.left_time = safe_atoi(cjson_data.left_time);
            if (Bed_Write.left_time != 0)
            {
                Bed_Time.lefttime_set = 1; // 左区定时任务标志位置一
                // 计算开始与结束时间
                get_time(&system_timestamp);
                Bed_Time.left_starttime = system_timestamp;
                Bed_Time.left_endtime = Bed_Time.left_starttime + Bed_Write.left_time * 60;
                printf("left_starttime = %lld,left_endtime = %lld\n", Bed_Time.left_starttime, Bed_Time.left_endtime);
            }
            else
            {
                Bed_Time.lefttime_set = 0;
                Bed_Time.left_starttime = 0;
                Bed_Time.left_endtime = 0;
                printf("取消左区定时\n");
            }
            err = nvs_open(Bed_Storage, NVS_READWRITE, &my_handle);
            err = nvs_set_blob(my_handle, "Bed_Time", &Bed_Time, sizeof(BedControlTime));
            if (err != ESP_OK)
            {
                printf("存储定时参数失败\n");
            }
            err = nvs_commit(my_handle);
            nvs_close(my_handle);
        }
        // 有右区定时任务
        if (Bed_Control_State[6] == 1)
        {
            Bed_Write.right_time = safe_atoi(cjson_data.right_time);
            if (Bed_Write.right_time != 0)
            {
                Bed_Time.righttime_set = 1; // 右区定时任务标志位置一
                // 计算开始与结束时间
                get_time(&system_timestamp);
                Bed_Time.right_starttime = system_timestamp;
                Bed_Time.right_endtime = Bed_Time.right_starttime + Bed_Write.right_time * 60;
                printf("right_starttime = %lld,right_endtime = %lld\n", Bed_Time.right_starttime, Bed_Time.right_endtime);
            }
            else
            {
                Bed_Time.righttime_set = 0; // 右区定时任务标志位置一
                Bed_Time.right_starttime = 0;
                Bed_Time.right_endtime = 0;
                printf("取消右区定时\n");
            }
            err = nvs_open(Bed_Storage, NVS_READWRITE, &my_handle);
            err = nvs_set_blob(my_handle, "Bed_Time", &Bed_Time, sizeof(BedControlTime));
            if (err != ESP_OK)
            {
                printf("存储定时参数失败\n");
            }
            err = nvs_commit(my_handle);
            nvs_close(my_handle);
        }
        if (Bed_Control_State[7] == 1)
        {
            Bed_Write.LED = safe_atoi(cjson_data.LED);
        }
        Publish_Reply_Message(my_client, g_publish_topic, true);
        while (bed_tx != 0)
        {
            vTaskDelay(5 / portTICK_PERIOD_MS);
        }
        bed_tx = 1; // 控制标志位置一
        // 记得存储床左右的开关状态以及定时时间结构体的各种参数

        // Bed_Write_State[2] = safe_atoi(cjson_data.left_upkey);
        // Bed_Write_State[3] = safe_atoi(cjson_data.right_upkey);
        // Bed_Write_State[4] = safe_atoi(cjson_data.cost);
        // Bed_Write_State[6] = safe_atoi(cjson_data.left_downkey);
        // Bed_Write_State[7] = safe_atoi(cjson_data.right_downkey);
        // if (safe_atoi(cjson_data.left_uptemp))
        // {
        //     Bed_Write.left_uptemp = safe_atoi(cjson_data.left_uptemp);
        // }
        // if (safe_atoi(cjson_data.left_downtemp))
        // {
        //     Bed_Write.left_downtemp = safe_atoi(cjson_data.left_downtemp);
        // }
        // if (safe_atoi(cjson_data.right_uptemp))
        // {
        //     Bed_Write.right_uptemp = safe_atoi(cjson_data.right_uptemp);
        // }
        // if (safe_atoi(cjson_data.right_downtemp))
        // {
        //     Bed_Write.right_downtemp = safe_atoi(cjson_data.right_downtemp);
        // }
        // // Bed_Write.left_uptemp = safe_atoi(cjson_data.left_uptemp);
        // // Bed_Write.left_downtemp = safe_atoi(cjson_data.left_downtemp);
        // // Bed_Write.right_uptemp = safe_atoi(cjson_data.right_uptemp);
        // // Bed_Write.right_downtemp = safe_atoi(cjson_data.right_downtemp);
        // Bed_Write.left_VibFreq = safe_atoi(cjson_data.left_VibFreq);
        // Bed_Write.left_VibInt = safe_atoi(cjson_data.left_VibInt);
        // Bed_Write.right_VibFreq = safe_atoi(cjson_data.right_VibFreq);
        // Bed_Write.right_VibInt = safe_atoi(cjson_data.right_VibInt);

        // if ((Bed_Write_State[2] != 1 && Bed_Write_State[2] != 0) || (Bed_Write_State[3] != 0 && Bed_Write_State[3] != 1) || (Bed_Write_State[4] != 0 && Bed_Write_State[4] != 1) || (Bed_Write_State[6] != 0 && Bed_Write_State[6] != 1) || (Bed_Write_State[7] != 0 && Bed_Write_State[7] != 1) || (Bed_Write.left_uptemp < 25 || Bed_Write.left_uptemp > 43) || (Bed_Write.left_downtemp < 25 || Bed_Write.left_downtemp > 43) || (Bed_Write.right_uptemp < 25 || Bed_Write.right_uptemp > 43) || (Bed_Write.right_downtemp < 25 || Bed_Write.right_downtemp > 43)) /**/
        // {

        //     Publish_Reply_Message(client, topic, false);
        // }
        // else
        // {
        //     printf("进入控制\n");
        //     BedControl(&client, topic); // 开始控制
        // }
    }
    if (strcmp(cjson_data.deviceType, "SmartDevice") == 0 &&
        strcmp(cjson_data.deviceMAC, mac_str) == 0 &&
        strcmp(cjson_data.operate, "query") == 0 &&
        strcmp(cjson_data.type, "controller") == 0 &&
        strcmp(cjson_data.sub_operate, "read") == 0) // 判断是读取床垫状态报文
    {
        ESP_LOGI(TAG, "It is read cmd!!!");
        int ret = Bed_ReadState(client, topic);
    }

    if (strcmp(cjson_data.deviceType, "SmartDevice") == 0 &&
        strcmp(cjson_data.type, "task") == 0 &&
        strcmp(cjson_data.sub_mode, "changereport") == 0) // 判断是状态改变任务开关
    {
        ESP_LOGI(TAG, "It is changeEN cmd!!!");
        if ((strcmp(cjson_data.sub_operate, "enable") == 0 || strcmp(cjson_data.sub_operate, "disable") == 0)) /**/
        {
            printf("cjson_data.operate:%s\n", cjson_data.sub_operate);
            nvs_handle_t my_handle;
            err = nvs_open(Bed_Storage, NVS_READWRITE, &my_handle);
            err = nvs_set_str(my_handle, "changeEN", cjson_data.sub_operate);
            if (err != ESP_OK)
            {
                printf("Error1 (%s) \n", esp_err_to_name(err));
            }
            err = nvs_commit(my_handle);
            if (err != ESP_OK)
            {
                printf("Error2 (%s) \n", esp_err_to_name(err));
            }
            size_t count = 0;
            err = nvs_get_str(my_handle, "changeEN", NULL, &count);
            char *changeEN = (char *)malloc(count);
            err = nvs_get_str(my_handle, "changeEN", changeEN, &count);
            printf("here_changeEn = %s\n", changeEN);

            nvs_close(my_handle);
            int check = Bed_Change_TaskKey();
            if (check == 1)
            {
                Publish_Reply_Message(client, topic, true);
            }
            else
            {
                Publish_Reply_Message(client, topic, false);
            }
        }
        else
        {
            ESP_LOGE(TAG, "changeEN cmd error!!!");
            Publish_Reply_Message(client, topic, false);
        }
    }

    if (strcmp(cjson_data.deviceType, "SmartDevice") == 0 &&
        strcmp(cjson_data.deviceMAC, mac_str) == 0 &&
        strcmp(cjson_data.operate, "sync") == 0 &&
        strcmp(cjson_data.type, "syncPolicyEn") == 0) // 判断是策略开关
    {
        ESP_LOGI(TAG, "It is syncPolicyEn cmd!!!");
        if ((strcmp(cjson_data.sub_policyEn, "enable") == 0 || strcmp(cjson_data.sub_policyEn, "disable") == 0) && (strcmp(cjson_data.sub_policyEnType, "onetime") == 0 || strcmp(cjson_data.sub_policyEnType, "onetimeWeek") == 0)) /**/
        {
            printf("syncPolicyEn cmd !!!\n");
            printf("policyEn:%s\n", cjson_data.sub_policyEn);
            printf("policyEnType:%s\n", cjson_data.sub_policyEnType);
            nvs_handle_t my_handle;
            esp_err_t err = nvs_open(Bed_Storage, NVS_READWRITE, &my_handle);
            if (strcmp(cjson_data.sub_policyEnType, "onetime") == 0) // 如果是操作一次性定时任务
            {
                err = nvs_set_str(my_handle, "onetimeEn", cjson_data.sub_policyEn);
            }
            else if (strcmp(cjson_data.sub_policyEnType, "onetimeWeek") == 0) // 如果是操作周讯定时任务
            {
                err = nvs_set_str(my_handle, "onetimeWeekEn", cjson_data.sub_policyEn);
            }
            int check = Bed_SyncPolicy_TaskKey();
            if (check == 1)
            {
                Publish_Reply_Message(client, topic, true);
            }
            else
            {
                Publish_Reply_Message(client, topic, false);
            }
        }
    }
    if (strcmp(cjson_data.deviceType, "SmartDevice") == 0 &&
        strcmp(cjson_data.deviceMAC, mac_str) == 0 &&
        strcmp(cjson_data.operate, "sync") == 0 &&
        strcmp(cjson_data.type, "syncPolicy") == 0) // 判断是同步策略报文
    {
        printf("syncPolicy cmd !!!\n");
        nvs_handle_t my_handle;
        esp_err_t err = nvs_open(Bed_Storage, NVS_READWRITE, &my_handle);

        Bed_Test_State[2] = safe_atoi(cjson_data.left_upkey);
        Bed_Test_State[3] = safe_atoi(cjson_data.right_upkey);
        Bed_Test_State[4] = safe_atoi(cjson_data.cost);
        Bed_Test_State[6] = safe_atoi(cjson_data.left_downkey);
        Bed_Test_State[7] = safe_atoi(cjson_data.right_downkey);
        if (safe_atoi(cjson_data.left_uptemp))
        {
            Bed_Test.left_uptemp = safe_atoi(cjson_data.left_uptemp);
        }
        if (safe_atoi(cjson_data.left_downtemp))
        {
            Bed_Test.left_downtemp = safe_atoi(cjson_data.left_downtemp);
        }
        if (safe_atoi(cjson_data.right_uptemp))
        {
            Bed_Test.right_uptemp = safe_atoi(cjson_data.right_uptemp);
        }
        if (safe_atoi(cjson_data.right_downtemp))
        {
            Bed_Test.right_downtemp = safe_atoi(cjson_data.right_downtemp);
        }

        // Bed_Test.left_uptemp = safe_atoi(cjson_data.left_uptemp);
        // Bed_Test.left_downtemp = safe_atoi(cjson_data.left_downtemp);
        // Bed_Test.right_uptemp = safe_atoi(cjson_data.right_uptemp);
        // Bed_Test.right_downtemp = safe_atoi(cjson_data.right_downtemp);
        Bed_Test.left_VibFreq = safe_atoi(cjson_data.left_VibFreq);
        Bed_Test.left_VibInt = safe_atoi(cjson_data.left_VibInt);
        Bed_Test.right_VibFreq = safe_atoi(cjson_data.right_VibFreq);
        Bed_Test.right_VibInt = safe_atoi(cjson_data.right_VibInt);

        if ((Bed_Test_State[2] != 1 && Bed_Test_State[2] != 0) || (Bed_Test_State[3] != 0 && Bed_Test_State[3] != 1) || (Bed_Test_State[6] != 0 && Bed_Test_State[6] != 1) || (Bed_Test_State[7] != 0 && Bed_Test_State[7] != 1) || (Bed_Test_State[4] != 0 && Bed_Test_State[4] != 1) || (Bed_Test.left_uptemp < 25 || Bed_Test.left_uptemp > 43) || (Bed_Test.left_downtemp < 25 || Bed_Test.left_downtemp > 43) || (Bed_Test.right_uptemp < 25 || Bed_Test.right_uptemp > 43) || (Bed_Test.right_downtemp < 25 || Bed_Test.right_downtemp > 43) || (strcmp(cjson_data.sub_deviceType, "BedControl") != 0) || (strcmp(cjson_data.sub_deviceId, mac_str) != 0)) //
        {
            // printf("Here\n");
            // printf("Bed_Test_State[2] = %d,Bed_Test_State[3] = %d,Bed_Test_State[6] = %d,Bed_Write.left_uptemp = %d,Bed_Write.right_downtemp = %d", Bed_Test_State[2], Bed_Test_State[3], Bed_Test_State[6], Bed_Test.left_uptemp, Bed_Test.right_downtemp);
            Publish_Reply_Message(client, topic, false);
        }
        else
        {
            ESP_LOGI(TAG, "It is syncPolicy cmd!!!");
            int err = Bed_SyncPolicy_Save(&cjson_data); // 存储同步策略的各种参数
            if (err == 1)
            {
                Publish_Reply_Message(client, topic, true);
            }
            else
            {
                Publish_Reply_Message(client, topic, false);
            }
        }
    }
    if (strcmp(cjson_data.deviceType, "SmartDevice") == 0 &&
        strcmp(cjson_data.type, "wifitest") == 0) // 判断是进入WIFI产测
    {
        printf(" It is wifitest cmd!!!\n");
        printf("接收到进入WIFI产测命令\n");
        // 产测标志位置一
        bed_test = 1;
        // 存储标志位
        nvs_handle_t my_handle;
        esp_err_t err;
        err = nvs_open("Wifi_Storage", NVS_READWRITE, &my_handle);
        err = nvs_set_i64(my_handle, "bed_test", bed_test);
        nvs_commit(my_handle);
        nvs_close(my_handle);
        printf("进入产测,开始重启");
        esp_restart();
    }

    if (strcmp(cjson_data.deviceMAC, mac_str) != 0)
    {
        Publish_Reply_Message(client, topic, false);
    }
}

int safe_atoi(const char *str)
{
    if (str != NULL && str[0] != '\0')
    { // 确保字符串不是NULL且不为空
        return atoi(str);
    }
    else
    {
        // 适当的错误处理: 返回0或错误代码，或记录错误
        return 0; // 或者选择一个适当的默认值
    }
}
/**
 * @description: 构建一个订阅主题
 * @param {char} *paket_data
 * @return {*}	ESP_LOGI(TAG, "client subscribe:%s", paket_data);
 */
void packet_subscribe_topic(char *paket_data)
{
    esp_read_mac(g_esp_mac, ESP_MAC_WIFI_STA); // 读取mac地址
    sprintf(mac_str, "%02x%02x%02x%02x%02x%02x", g_esp_mac[0], g_esp_mac[1], g_esp_mac[2], g_esp_mac[3], g_esp_mac[4], g_esp_mac[5]);
    ESP_LOGI(TAG, "mac trans:%s", mac_str); // 将mac转换成字符串
    char topic_client[] = "ALIVE/CLIENT/";
    char topic_gateway[] = "RDBed/";
    char topic_multi_layer_wildcard[] = "/#";

    strcat(paket_data, topic_client);
    strcat(paket_data, topic_gateway);
    strcat(paket_data, mac_str);
    strcat(paket_data, topic_multi_layer_wildcard);

    ESP_LOGI(TAG, "client subscribe:%s", paket_data);
}

/**
 * @description: 构建一个发布主题
 * @param {char} *paket_data
 * @return {*}	ESP_LOGI(TAG, "client subscribe:%s", paket_data);
 */
void packet_publish_topic(char *paket_data)
{
    char xlink_client_id[14] = {0};
    esp_read_mac(g_esp_mac, ESP_MAC_WIFI_STA); // 读取mac地址
    sprintf(mac_str, "%02x%02x%02x%02x%02x%02x", g_esp_mac[0], g_esp_mac[1], g_esp_mac[2], g_esp_mac[3], g_esp_mac[4], g_esp_mac[5]);
    ESP_LOGI(TAG, "mac trans:%s", mac_str); // 将mac转换成字符串

    char topic_client[] = "ALIVE/SERVER/";
    char topic_gateway[] = "RDBed/";
    sprintf(xlink_client_id, "%d", CONFIG_XLINK_DEVICE_ID);
    strcat(paket_data, topic_client);
    strcat(paket_data, topic_gateway);
    strcat(paket_data, mac_str);
    strcat(paket_data, "/");
    strcat(paket_data, xlink_client_id);

    // strcat(paket_data, topic_multi_layer_wildcard);

    ESP_LOGI(TAG, "client publish:%s", paket_data);
}

// 发布首次连接

void Publish_First_Connet(esp_mqtt_client_handle_t *client)
{
    nvs_handle_t my_handle;
    static const char *TAG1 = "First_Connet";
    mbedtls_md5_context md5_ctx;
    char wait_encrypt_str[255] = {0};
    unsigned char decrypt[16];
    char decrypt_cs[33];
    printf("发布首次连接\n");
    cJSON *attributes = cJSON_CreateObject();
    cJSON *content;
    cJSON *sub_content;
    cJSON_AddStringToObject(attributes, "deviceType", "SmartDevice");
    cJSON_AddStringToObject(attributes, "subType", "SmartBed");
    cJSON_AddStringToObject(attributes, "deviceMAC", mac_str);
    cJSON_AddStringToObject(attributes, "familyId", "0");
    cJSON_AddStringToObject(attributes, "groupId", "0");
    cJSON_AddStringToObject(attributes, "operate", "report");
    // content对象
    cJSON_AddItemToObject(attributes, "content", content = cJSON_CreateObject());
    cJSON_AddStringToObject(content, "type", "virgin");
    // 内部content
    cJSON_AddItemToObject(content, "content", sub_content = cJSON_CreateArray());
    cJSON *item_tmp = cJSON_CreateObject();

    const esp_partition_t *running = esp_ota_get_running_partition(); // 获取当前运行的应用程序的分区信息
    esp_app_desc_t running_app_info;
    if (esp_ota_get_partition_description(running, &running_app_info) == ESP_OK)
    {
        printf("Running firmware version: %s", running_app_info.version);
    }
    cJSON_AddStringToObject(item_tmp, "PROJECT_VER", running_app_info.version);
    cJSON_AddStringToObject(item_tmp, "mqttSubjectPlan", "wss://mesh.szalive.com:8084/mqtt");
    nvs_stats_t nvs_stats;
    nvs_get_stats(NULL, &nvs_stats);
    printf("Count: UsedEntries = (%d), FreeEntries = (%d), AllEntries = (%d)\n",
           nvs_stats.used_entries, nvs_stats.free_entries, nvs_stats.total_entries);
    // Count: UsedEntries = (174), FreeEntries = (330), AllEntries = (504)
    //			已用表目				免费的条目 			所有条目
    int syy_n_brightness = 0;
    char syy_na_brightness[5] = {0};
    syy_n_brightness = nvs_stats.used_entries;
    itoa(syy_n_brightness, syy_na_brightness, 10);
    cJSON_AddStringToObject(item_tmp, "used_entries", syy_na_brightness);
    syy_n_brightness = nvs_stats.free_entries;
    itoa(syy_n_brightness, syy_na_brightness, 10);
    cJSON_AddStringToObject(item_tmp, "free_entries", syy_na_brightness);
    syy_n_brightness = nvs_stats.total_entries;
    itoa(syy_n_brightness, syy_na_brightness, 10);
    cJSON_AddStringToObject(item_tmp, "total_entries", syy_na_brightness);
    cJSON_AddItemToArray(sub_content, item_tmp);
    char source[] = "Alive";
    cJSON_AddStringToObject(attributes, "source", source);
    cJSON_AddStringToObject(attributes, "version", "v0.1");
    get_time(&system_timestamp);
    ESP_LOGI(TAG1, "The timestamp is %lld \n", system_timestamp);
    char timestamp[14];
    sprintf(timestamp, "%lld", system_timestamp);
    cJSON_AddStringToObject(attributes, "timestamp", timestamp);
    // md5校验
    strcat(wait_encrypt_str, "Alive");
    strcat(wait_encrypt_str, source);
    strcat(wait_encrypt_str, timestamp);
    mbedtls_md5_init(&md5_ctx);
    mbedtls_md5_starts(&md5_ctx);
    mbedtls_md5_update(&md5_ctx, (unsigned char *)wait_encrypt_str, strlen((char *)wait_encrypt_str));
    mbedtls_md5_finish(&md5_ctx, decrypt);
    sprintf(decrypt_cs, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", decrypt[0], decrypt[1], decrypt[2], decrypt[3], decrypt[4], decrypt[5], decrypt[6], decrypt[7], decrypt[8], decrypt[9],
            decrypt[10], decrypt[11], decrypt[12], decrypt[13], decrypt[14], decrypt[15]);
    mbedtls_md5_free(&md5_ctx);
    cJSON_AddStringToObject(attributes, "sign", (char *)decrypt_cs);
    cJSON_AddStringToObject(attributes, "append", cjson_data.append);
    // 发布
    char *ptr = cJSON_Print(attributes);
    // int msg_id = esp_mqtt_client_publish(client, "ALIVE/SERVER/GateWayBle/30c6f7f7a4d0/12345", ptr, 0, 0, 0);
    int msg_id = esp_mqtt_client_publish(client, g_publish_topic, ptr, 0, 0, 0);
    if (ptr != NULL)
    {
        cJSON_free(ptr);
        ptr = NULL;
    }
    cJSON_Delete(attributes);
}

// void Publish_First_Connet(esp_mqtt_client_handle_t *client)
// {
//     printf("发布首次连接\n");
//     cJSON *attributes = cJSON_CreateObject();
//     cJSON *content;
//     cJSON *sub_content;
//     cJSON_AddStringToObject(attributes, "deviceType", "SmartDevice");
//     cJSON_AddStringToObject(attributes, "subType", "RDBed");
//     cJSON_AddStringToObject(attributes, "deviceMAC", mac_str);
//     cJSON_AddStringToObject(attributes, "familyId", "0");
//     cJSON_AddStringToObject(attributes, "groupId", "0");
//     cJSON_AddStringToObject(attributes, "operate", "report");
//     // content对象
//     cJSON_AddItemToObject(attributes, "content", content = cJSON_CreateObject());
//     cJSON_AddStringToObject(content, "type", "virgin");
//     // 内部content
//     cJSON_AddItemToObject(content, "content", sub_content = cJSON_CreateArray());
//     cJSON *item_tmp = cJSON_CreateObject();
//     cJSON_AddStringToObject(item_tmp, "PROJECT_VER", "BLEGWV1_0_14");
//     cJSON_AddStringToObject(item_tmp, "mqttSubjectPlan", "wss://mesh.szalive.com:8084/mqtt");
//     cJSON_AddStringToObject(item_tmp, "used_entries", "167");
//     cJSON_AddStringToObject(item_tmp, "free_entries", "28057");
//     cJSON_AddStringToObject(item_tmp, "total_entries", "28224");
//     cJSON_AddItemToArray(sub_content, item_tmp);
//     char source[] = "Alive";
//     cJSON_AddStringToObject(attributes, "source", source);
//     cJSON_AddStringToObject(attributes, "version", "v0.1");
//     cJSON_AddStringToObject(attributes, "timestamp", "1647246643135");
//     cJSON_AddStringToObject(attributes, "sign", "986fd8465e805b91f267d8af09f40ae2");
//     cJSON_AddStringToObject(attributes, "append", cjson_data.append);
//     // 发布
//     char *ptr = cJSON_Print(attributes);
//     // int msg_id = esp_mqtt_client_publish(client, "ALIVE/SERVER/GateWayBle/30c6f7f7a4d0/12345", ptr, 0, 0, 0);
//     int msg_id = esp_mqtt_client_publish(client, g_publish_topic, ptr, 0, 0, 0);
//     if (ptr != NULL)
//     {
//         cJSON_free(ptr);
//         ptr = NULL;
//     }
//     cJSON_Delete(attributes);
// }

// 上报首次连接回复报文解析
int get_first_jsondata(cJSON *rx_json, myCJson *data)
{
    static const char *TAG = "First jsondata";

    mbedtls_md5_context md5_ctx;
    char wait_encrypt_str[255] = {0};
    unsigned char decrypt[16];
    char decrypt_cs[33];

    if (rx_json == NULL || data == NULL)
    {
        return 0;
    }
    // ESP_LOGI(TAG, "%s", cJSON_Print(rx_json));

    if (cJSON_GetObjectItem(rx_json, "deviceType") == NULL)
    {
        printf("rx json have no deviceType Item!\n");

        return 0;
    }
    data->deviceType = cJSON_GetObjectItem(rx_json, "deviceType")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "subType") == NULL)
    {
        printf("rx json have no subType Item!\n");

        return 0;
    }
    data->subType = cJSON_GetObjectItem(rx_json, "subType")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "deviceMAC") == NULL)
    {
        printf("rx json have no deviceMAC Item!\n");

        return 0;
    }
    data->deviceMAC = cJSON_GetObjectItem(rx_json, "deviceMAC")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "groupId") == NULL)
    {
        printf("rx json have no groupId Item!\n");

        return 0;
    }
    data->groupId = cJSON_GetObjectItem(rx_json, "groupId")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "familyId") == NULL)
    {
        printf("rx json have no familyId Item!\n");

        return 0;
    }
    data->familyId = cJSON_GetObjectItem(rx_json, "familyId")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "operate") == NULL)
    {
        printf("rx json have no operate Item!\n");

        return 0;
    }
    data->operate = cJSON_GetObjectItem(rx_json, "operate")->valuestring;

    cJSON *sub_content = cJSON_GetObjectItem(rx_json, "content");
    int sub_content_obj_size = cJSON_GetArraySize(sub_content); // 获取第二层"content "的项目数
    ESP_LOGI(TAG, "ARRAY SIZE:%d", sub_content_obj_size);

    if (cJSON_GetObjectItem(sub_content, "msg") == NULL)
    {
        printf("rx json have no msg Item!\n");

        return 0;
    }
    data->msg = cJSON_GetObjectItem(sub_content, "msg")->valuestring;

    if (cJSON_GetObjectItem(sub_content, "code") == NULL)
    {
        printf("rx json have no code Item!\n");

        return 0;
    }
    data->code = cJSON_GetObjectItem(sub_content, "code")->valuestring;

    if (cJSON_GetObjectItem(sub_content, "timeStr") == NULL)
    {
        printf("rx json have no timeStr Item!\n");

        return 0;
    }
    data->timeStr = cJSON_GetObjectItem(sub_content, "timeStr")->valuestring;

    if (cJSON_GetObjectItem(sub_content, "timestamp") == NULL)
    {
        printf("rx json have no timestamp Item!\n");

        return 0;
    }
    data->sub_timestamp = cJSON_GetObjectItem(sub_content, "timestamp")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "source") == NULL)
    {
        printf("rx json have no source Item!\n");

        return 0;
    }
    data->source = cJSON_GetObjectItem(rx_json, "source")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "version") == NULL)
    {
        printf("rx json have no version Item!\n");

        return 0;
    }
    data->version = cJSON_GetObjectItem(rx_json, "version")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "timestamp") == NULL)
    {
        printf("rx json have no timestamp Item!\n");

        return 0;
    }
    data->timestamp = cJSON_GetObjectItem(rx_json, "timestamp")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "sign") == NULL)
    {
        printf("rx json have no sign Item!\n");

        return 0;
    }
    data->sign = cJSON_GetObjectItem(rx_json, "sign")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "append") == NULL)
    {
        printf("rx json have no append Item!\n");

        return 0;
    }
    data->append = cJSON_GetObjectItem(rx_json, "append")->valuestring;
    strcpy(Json_Append, data->append);
    // 记得把md5校验补了
    strcat(wait_encrypt_str, "Alive");
    strcat(wait_encrypt_str, data->source);
    strcat(wait_encrypt_str, data->timestamp);
    mbedtls_md5_init(&md5_ctx);
    mbedtls_md5_starts(&md5_ctx);
    mbedtls_md5_update(&md5_ctx, (unsigned char *)wait_encrypt_str, strlen((char *)wait_encrypt_str));
    mbedtls_md5_finish(&md5_ctx, decrypt);
    sprintf(decrypt_cs, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", decrypt[0], decrypt[1], decrypt[2], decrypt[3], decrypt[4], decrypt[5], decrypt[6], decrypt[7], decrypt[8], decrypt[9],
            decrypt[10], decrypt[11], decrypt[12], decrypt[13], decrypt[14], decrypt[15]);
    mbedtls_md5_free(&md5_ctx);

    if (strcmp((char *)decrypt_cs, data->sign) == 0) // 校验正确
    {
        ESP_LOGI(TAG, "MD5 success!!!\n");
        return 1;
    }
    else
    {
        ESP_LOGI(TAG, "MD5 failed !!!\n");
    }
    return 0;
}

// 解析json数据
int Parse_JsonData(cJSON *rx_json, myCJson *data)
{
    mbedtls_md5_context md5_ctx;
    char wait_encrypt_str[255] = {0};
    unsigned char decrypt[16];
    char decrypt_cs[33];

    static const char *TAG = "Parse_Json";
    if (rx_json == NULL || data == NULL)
    {
        return 0;
    }
    if (cJSON_GetObjectItem(rx_json, "deviceType") == NULL)
    {
        printf("rx json have no deviceType Item!\n");

        return 0;
    }
    data->deviceType = cJSON_GetObjectItem(rx_json, "deviceType")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "subType") == NULL)
    {
        printf("rx json have no subType Item!\n");

        return 0;
    }
    data->subType = cJSON_GetObjectItem(rx_json, "subType")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "deviceMAC") == NULL)
    {
        printf("rx json have no deviceMAC Item!\n");

        return 0;
    }
    data->deviceMAC = cJSON_GetObjectItem(rx_json, "deviceMAC")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "groupId") == NULL)
    {
        printf("rx json have no groupId Item!\n");

        return 0;
    }
    data->groupId = cJSON_GetObjectItem(rx_json, "groupId")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "familyId") == NULL)
    {
        printf("rx json have no familyId Item!\n");

        return 0;
    }
    data->familyId = cJSON_GetObjectItem(rx_json, "familyId")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "operate") == NULL)
    {
        printf("rx json have no operate Item!\n");

        return 0;
    }
    data->operate = cJSON_GetObjectItem(rx_json, "operate")->valuestring;

    cJSON *content = cJSON_GetObjectItem(rx_json, "content");

    if (cJSON_GetObjectItem(content, "type") == NULL)
    {
        printf("rx json have no operate Item!\n");

        return 0;
    }
    data->type = cJSON_GetObjectItem(content, "type")->valuestring;

    cJSON *sub_content = cJSON_GetObjectItem(content, "content");

    cJSON *item = cJSON_GetArrayItem(sub_content, 0);

    // if (cJSON_GetObjectItem(item, "Bed_Write_State") == NULL)
    // {
    //     printf("rx json have no Bed_Write_State Item!\n");
    // }
    // else
    // {
    //     data->Bed_Write_State = cJSON_GetObjectItem(item, "Bed_Write_State")->valuestring;
    // }
    // 下面是OTA升级的参数
    if (cJSON_GetObjectItem(item, "downloadLink") == NULL)
    {
        printf("rx json have no downloadLink!\n");
    }
    else
    {
        data->sub_downloadLink = cJSON_GetObjectItem(item, "downloadLink")->valuestring;
    }
    // 下面是床垫状态任务的参数
    if (cJSON_GetObjectItem(item, "mode") == NULL)
    {
        printf("rx json have no sub_mode!\n");
    }
    else
    {
        data->sub_mode = cJSON_GetObjectItem(item, "mode")->valuestring;
    }
    // 下面是策略的参数
    if (cJSON_GetObjectItem(item, "condition") == NULL)
    {
        printf("rx json have no condition!\n");
    }
    else
    {
        cJSON *sub_condition = cJSON_GetObjectItem(item, "condition");
        cJSON *time = cJSON_GetObjectItem(sub_condition, "time");
        cJSON *time_item = cJSON_GetArrayItem(time, 0);
        cJSON *device = cJSON_GetObjectItem(sub_condition, "device");
        cJSON *device_item = cJSON_GetArrayItem(device, 0);
        cJSON *action = cJSON_GetObjectItem(sub_condition, "action");
        cJSON *action_item = cJSON_GetArrayItem(action, 0);
        // time
        if (cJSON_GetObjectItem(time_item, "type") == NULL)
        {
            printf("rx json have no time_type!\n");
            return 0;
        }
        else
        {
            data->sub_type = cJSON_GetObjectItem(time_item, "type")->valuestring;
        }
        if (cJSON_GetObjectItem(time_item, "date") == NULL)
        {
            printf("rx json have no time_data!\n");
        }
        else
        {
            data->sub_date = cJSON_GetObjectItem(time_item, "date")->valuestring;
        }
        if (cJSON_GetObjectItem(time_item, "time") == NULL)
        {
            printf("rx json have no time_time!\n");
            return 0;
        }
        else
        {
            data->sub_time = cJSON_GetObjectItem(time_item, "time")->valuestring;
        }
        if (cJSON_GetObjectItem(time_item, "week") == NULL)
        {
            printf("rx json have no time_week!\n");
        }
        else
        {
            data->sub_week = cJSON_GetObjectItem(time_item, "week")->valuestring;
        }
        // device
        if (cJSON_GetObjectItem(device_item, "deviceType") == NULL)
        {
            printf("rx json have no device_deviceType!\n");
            return 0;
        }
        else
        {
            data->sub_deviceType = cJSON_GetObjectItem(device_item, "deviceType")->valuestring;
        }
        if (cJSON_GetObjectItem(device_item, "deviceId") == NULL)
        {
            printf("rx json have no device_deviceId!\n");
            return 0;
        }
        else
        {
            data->sub_deviceId = cJSON_GetObjectItem(device_item, "deviceId")->valuestring;
        }
        // action
        GetBedJson_Control_State(data, action_item, 1);
    }
    // 下面是查询时的参数
    if (cJSON_GetObjectItem(item, "operate") == NULL)
    {
        printf("rx json have no sub_operate!\n");
    }
    else
    {
        data->sub_operate = cJSON_GetObjectItem(item, "operate")->valuestring;
    }
    GetBedJson_Control_State(data, item, 0); // 控制床垫的参数

    if (cJSON_GetObjectItem(item, "policyEn") == NULL)
    {
        printf("rx json have no policyEn!\n");
    }
    else
    {
        data->sub_policyEn = cJSON_GetObjectItem(item, "policyEn")->valuestring;
    }

    if (cJSON_GetObjectItem(item, "policyType") == NULL)
    {
        printf("rx json have no policyEnType!\n");
    }
    else
    {
        data->sub_policyEnType = cJSON_GetObjectItem(item, "policyType")->valuestring;
    }

    if (cJSON_GetObjectItem(rx_json, "source") == NULL)
    {
        printf("rx json have no source Item!\n");

        return 0;
    }
    data->source = cJSON_GetObjectItem(rx_json, "source")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "version") == NULL)
    {
        printf("rx json have no version Item!\n");

        return 0;
    }
    data->version = cJSON_GetObjectItem(rx_json, "version")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "timestamp") == NULL)
    {
        printf("rx json have no timestamp Item!\n");

        return 0;
    }
    data->timestamp = cJSON_GetObjectItem(rx_json, "timestamp")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "sign") == NULL)
    {
        printf("rx json have no sign Item!\n");

        return 0;
    }
    data->sign = cJSON_GetObjectItem(rx_json, "sign")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "append") == NULL)
    {
        printf("rx json have no sign Item!\n");
        data->append = "0\0";
    }
    else
    {
        data->append = cJSON_GetObjectItem(rx_json, "append")->valuestring;
        strcpy(Json_Append, data->append);
    }

    // 记得把md5校验补了
    strcat(wait_encrypt_str, "Alive");
    strcat(wait_encrypt_str, data->source);
    strcat(wait_encrypt_str, data->timestamp);
    mbedtls_md5_init(&md5_ctx);
    mbedtls_md5_starts(&md5_ctx);
    mbedtls_md5_update(&md5_ctx, (unsigned char *)wait_encrypt_str, strlen((char *)wait_encrypt_str));
    mbedtls_md5_finish(&md5_ctx, decrypt);
    sprintf(decrypt_cs, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", decrypt[0], decrypt[1], decrypt[2], decrypt[3], decrypt[4], decrypt[5], decrypt[6], decrypt[7], decrypt[8], decrypt[9],
            decrypt[10], decrypt[11], decrypt[12], decrypt[13], decrypt[14], decrypt[15]);
    mbedtls_md5_free(&md5_ctx);

    if (strcmp((char *)decrypt_cs, data->sign) == 0) // 校验正确
    {
        ESP_LOGI(TAG, "MD5 success!!!\n");
        return 1;
    }
    else
    {
        ESP_LOGI(TAG, "MD5 failed !!!\n");
    }
    return 0;
}

// 当第一次获得时间戳时设置系统时间
void Get_system_time(uint64_t *timestamp, myCJson *data)
{

    uint64_t cjson_timestamp = strtoull(data->sub_timestamp, NULL, 10); // strtoull函数是一个用于将字符串转换为uint64_t(unsigned long long)类型的整数的标准库函数这里的10指的是十进制
    printf("cjson_timestamp = %lld\n", cjson_timestamp);
    if (cjson_timestamp != 0)
    {
        *timestamp = cjson_timestamp;
        // *timestamp = 1685496726073;
        set_system_time(*timestamp);
    }
}
